package com.ruoyi.project.system.role.controller;

import cn.hutool.json.JSONUtil;
import com.ruoyi.common.constant.IAMConstants;
import com.ruoyi.common.exception.IAMException;
import com.ruoyi.framework.shiro.util.SignBuilder;
import com.ruoyi.framework.shiro.util.secret.MD5Util;
import com.ruoyi.framework.shiro.util.secret.SecurityUtil;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.system.role.domain.recycle.*;
import com.ruoyi.project.system.role.service.RecycleService;
import com.ruoyi.project.system.third.domain.Third;
import com.ruoyi.project.system.third.service.ThirdService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;

/**
 * @author renzhihao
 * @date 2023/12/08 16:13
 */
@RestController
@RequestMapping("/recycle")
public class AppDataRecycleController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(AppDataRecycleController.class);

    @Autowired
    private ThirdService thirdService;

    @Autowired
    private RecycleService recycleService;

    @PostMapping("account")
    public AjaxResult recycleAccount(@RequestBody RecycleAppData recycleAppData, HttpServletRequest request) {
        log.info("接收到部门/用户回收请求");
        log.info("{}", recycleAppData);
        String servletPath = request.getServletPath();
        String method = request.getMethod();

        return iamSuccess(recycleUserDept(recycleAppData, method, servletPath));
    }

    @PostMapping("dept")
    public AjaxResult recycleDept(@RequestBody RecycleAppData recycleAppData, HttpServletRequest request) {
        log.info("接收到部门回收请求");
        log.info("{}", recycleAppData);
        String servletPath = request.getServletPath();
        String method = request.getMethod();

        return iamSuccess(recycleUserDept(recycleAppData, method, servletPath));
    }


    @PostMapping("user")
    public AjaxResult recycleUser(@RequestBody RecycleAppData recycleAppData, HttpServletRequest request) {
        log.info("接收到账号回收请求");
        log.info("{}", recycleAppData);
        String servletPath = request.getServletPath();
        String method = request.getMethod();

        return iamSuccess(recycleUserDept(recycleAppData, method, servletPath));
    }

    @GetMapping
    public String recycle(RecycleAppData recycleAppData, HttpServletRequest request) {
        log.info("接收到角色回收请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();
        return recycle(recycleAppData, method, servletPath);
    }

    @GetMapping("role")
    public String recycleRole(RecycleAppData recycleAppData, HttpServletRequest request) {
        log.info("接收到角色回收请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();
        return recycle(recycleAppData, method, servletPath);
    }

    @GetMapping("permission")
    public String recyclePermission(RecycleAppData recycleAppData, HttpServletRequest request) {
        log.info("接收到权限回收请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();
        return recycle(recycleAppData, method, servletPath);
    }

    @GetMapping("rolePermission")
    public String recycleRolePermission(RecycleAppData recycleAppData, HttpServletRequest request) {
        log.info("接收到角色权限关联关系回收请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();
        return recycle(recycleAppData, method, servletPath);
    }

    @GetMapping("permissionAccount")
    public String recyclePermissionAccount(RecycleAppData recycleAppData, HttpServletRequest request) {
        log.info("接收到权限账号关联关系回收请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();
        return recycle(recycleAppData, method, servletPath);
    }

    @GetMapping("roleAccount")
    public String recycleRoleAccount(RecycleAppData recycleAppData, HttpServletRequest request) {
        log.info("接收到角色账号关联关系回收请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();
        return recycle(recycleAppData, method, servletPath);
    }


    private String recycleUserDept(RecycleAppData recycleAppData, String method, String path) {
        Third third = thirdService.selectThirdAuth();
        String appSecret = third.getAppSecret();
        String appId = third.getAppId();

        String secret = MD5Util.getMD5String(appSecret);
        String sign = SignBuilder.create(appId, secret)
                .requestPath(path)
                .requestMethod(method.toUpperCase())
                .param("timestamp", recycleAppData.getTimestamp())
                .salt(recycleAppData.getSalt())
                .sign();

        if (!StringUtils.equalsIgnoreCase(sign, recycleAppData.getSign())) {
            throw new IAMException("签名校验失败");
        }

        if (Objects.equals(recycleAppData.getDataType(), IAMConstants.SYNC_DEPT)) {
            List<IAMRecycleDept> depts = recycleService.recycleDept();
            return SecurityUtil.encryptAES(JSONUtil.toJsonStr(depts), secret);
        } else if (Objects.equals(recycleAppData.getDataType(), IAMConstants.SYNC_ACCOUNT)) {
            List<IAMRecycleUser> users = recycleService.recycleUser();
            return SecurityUtil.encryptAES(JSONUtil.toJsonStr(users), secret);
        }

        throw new IAMException("未找到对应数据类型");
    }

    private String recycle(RecycleAppData recycleAppData, String method, String path) {
        log.info("当前数据类型：{}", recycleAppData.getDataType());
        Third third = thirdService.selectThirdAuth();
        String key = third.getDataKey();

        String sign = SignBuilder.create(recycleAppData.getClientId(), key)
                .requestPath(path)
                .requestMethod(method.toUpperCase())
                .param("timestamp", recycleAppData.getTimestamp())
                .param("dataType", recycleAppData.getDataType())
                .param("page", recycleAppData.getPage())
                .param("pageSize", recycleAppData.getPageSize())
                .salt(recycleAppData.getSalt())
                .sign();

        if (!StringUtils.equalsIgnoreCase(sign, recycleAppData.getSign())) {
            throw new IAMException("签名校验失败");
        }

        if (Objects.equals(recycleAppData.getDataType(), IAMConstants.SYNC_PERMISSION)) {
            RecycleResult<IAMRecyclePermission> result = recycleService.recyclePermission(recycleAppData.getPage(), recycleAppData.getPageSize());
            return SecurityUtil.encryptAES(JSONUtil.toJsonStr(result), key);
        }

        if (Objects.equals(recycleAppData.getDataType(), IAMConstants.SYNC_ROLE)) {
            RecycleResult<IAMRecycleRole> result = recycleService.recycleRole(recycleAppData.getPage(), recycleAppData.getPageSize());
            return SecurityUtil.encryptAES(JSONUtil.toJsonStr(result), key);
        }

        if (Objects.equals(recycleAppData.getDataType(), IAMConstants.SYNC_ROLE_PERMISSION)) {
            RecycleResult<IAMRecycleRolePermission> result = recycleService.recycleRolePermission(recycleAppData.getPage(), recycleAppData.getPageSize());
            return SecurityUtil.encryptAES(JSONUtil.toJsonStr(result), key);
        }

        if (Objects.equals(recycleAppData.getDataType(), IAMConstants.SYNC_ROLE_ACCOUNT)) {
            RecycleResult<IAMRecycleRoleAccount> result = recycleService.recycleRoleAccount(recycleAppData.getPage(), recycleAppData.getPageSize());
            return SecurityUtil.encryptAES(JSONUtil.toJsonStr(result), key);
        }

        if (Objects.equals(recycleAppData.getDataType(), IAMConstants.SYNC_PERMISSION_ACCOUNT)) {
            RecycleResult<IAMRecyclePermissionAccount> result = recycleService.recyclePermissionAccount(recycleAppData.getPage(), recycleAppData.getPageSize());
            return SecurityUtil.encryptAES(JSONUtil.toJsonStr(result), key);
        }

        throw new IAMException("未找到对应数据类型");
    }
}
